﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace cubeworld
{
    class Camera
    {

        public Matrix view;
        public Matrix projection;

        public Vector3 position;
        public Vector3 lookAt;

        Matrix rotationMatrix;

        int oldX, oldY;

        bool move, mouseRotate;
        float moveSpeed, rotateSpeed;

        public float yaw = 0;
        public float pitch = 0;

        public Camera(Vector3 position, Vector3 dir, float renderDistance)
        {
            this.position = position;
            lookAt = dir;
            SetUpView(position, dir);
            SetUpProjection(renderDistance);
        }

        private void SetUpView(Vector3 position, Vector3 dir)
        {
            view = Matrix.CreateLookAt(position, dir, Vector3.Up);
        }

        private void SetUpProjection(float renderDistance)
        {
            projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, MainGame.Device.Viewport.AspectRatio, 0.1f, renderDistance);
        }

        public void SetUpMovement(bool move, bool mouseRotate, float moveSpeed, float rotateSpeed)
        {
            this.move = move;
            this.mouseRotate = mouseRotate;

            this.moveSpeed = moveSpeed;
            this.rotateSpeed = rotateSpeed;
        }

        public void Update()
        {
            if (move)
            {
                KeyboardState keyState = Keyboard.GetState();

                if (keyState.IsKeyDown(Keys.W))
                {
                    Vector3 v = Vector3.Forward * moveSpeed;

                    Matrix forwardMovement = Matrix.CreateRotationY(yaw);
                    v = Vector3.Transform(v, forwardMovement);
                    position.Z += v.Z;
                    position.X += v.X;
                }

                if (keyState.IsKeyDown(Keys.S))
                {
                    Vector3 v = Vector3.Backward * moveSpeed;

                    Matrix forwardMovement = Matrix.CreateRotationY(yaw);
                    v = Vector3.Transform(v, forwardMovement);
                    position.Z += v.Z;
                    position.X += v.X;
                }

                if (keyState.IsKeyDown(Keys.D))
                {
                    Vector3 v = Vector3.Right * moveSpeed;

                    Matrix forwardMovement = Matrix.CreateRotationY(yaw);
                    v = Vector3.Transform(v, forwardMovement);
                    position.Z += v.Z;
                    position.X += v.X;
                }

                if (keyState.IsKeyDown(Keys.A))
                {
                    Vector3 v = Vector3.Left * moveSpeed;

                    Matrix forwardMovement = Matrix.CreateRotationY(yaw);
                    v = Vector3.Transform(v, forwardMovement);
                    position.Z += v.Z;
                    position.X += v.X;
                }

                if (keyState.IsKeyDown(Keys.E))
                {
                    Vector3 v = Vector3.Up * moveSpeed;

                    Matrix forwardMovement = Matrix.CreateRotationY(yaw);
                    v = Vector3.Transform(v, forwardMovement);
                    position.Z += v.Z;
                    position.X += v.X;
                    position.Y += v.Y;
                }

                if (keyState.IsKeyDown(Keys.Q))
                {
                    Vector3 v = Vector3.Down * moveSpeed;

                    Matrix forwardMovement = Matrix.CreateRotationY(yaw);
                    v = Vector3.Transform(v, forwardMovement);
                    position.Z += v.Z;
                    position.X += v.X;
                    position.Y += v.Y;
                }
            }

            if (mouseRotate)
            {
                MouseState mouse = Mouse.GetState();

                int dx = mouse.X - oldX;
                yaw -= rotateSpeed * dx;
                int dy = mouse.Y - oldY;
                pitch -= rotateSpeed * dy;

                if (pitch > 1.5f)
                    pitch = 1.5f;
                if (pitch < -1.5f)
                    pitch = -1.5f;

                MainGame.Win.Title = "YAW: " + yaw + "   PITCH: " + pitch;

                ResetCursor();
            }


            UpdateMatrices();
        }

        private void ResetCursor()
        {
            Mouse.SetPosition(MainGame.Device.Viewport.Width / 2, MainGame.Device.Viewport.Height / 2);
            oldX = MainGame.Device.Viewport.Width / 2;
            oldY = MainGame.Device.Viewport.Height / 2;
        }

        private void UpdateMatrices()
        {
            rotationMatrix = Matrix.CreateFromYawPitchRoll(yaw, pitch, 0);
            Vector3 transReference = Vector3.Transform(Vector3.Forward, rotationMatrix);
            Vector3 lookAt = position + transReference;

            view = Matrix.CreateLookAt(position, lookAt, Vector3.Up);
        }
    }
}
